package cn.ad.server.web.log;

import cn.ad.server.common.utils.IPUtils;
import cn.ad.server.web.log.entity.AdActiveEventLog;
import cn.ad.server.web.log.entity.AdTrackingEventLog;
import cn.ad.server.web.log.entity.AdTrafficHttpLog;
import cn.ad.server.web.log.entity.AdserverEventLog;
import cn.ad.server.web.spring.service.actions.context.AdContext;
import cn.ad.server.web.spring.service.actions.context.BidContext;
import cn.ad.server.web.spring.service.actions.presentation.ClickPresentation;
import cn.ad.server.web.spring.service.actions.presentation.WinNoticePresentation;
import org.apache.logging.log4j.LogManager;
import org.slf4j.LoggerFactory;

import java.util.regex.Pattern;

/**
 * Adserver事务事件日志记录实现类
 * 本类采用了log4j2来完成业务日志，设置系统所有的日志都将采用异步的方式来实现日志处理
 * @author Wu Chengjun
 */
public class AdServerEventLogger implements IAdServerLogger, IAdEventLogger {

	/**
	 * 系统默认日志
	 */
	private final static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AdServerEventLogger.class);

	/**
	 * Adrequest日志名称，用于获取系统配置日志Logger对象
	 */
	private static final String ADREQUEST_LOG_NAME = "adrequest";

	/**
	 * Adevent日志名称, 用于获取系统配置的日志Logger对象
	 */
	public static final String ADEVENT_LOG_NAME = "adevent";
	
	/**
	 * Adrequest日志名称，用于获取系统配置日志Logger对象
	 */
	private static final String ADBIDREQUEST_LOG_NAME = "adbidrequest";
	
	/**
	 * http请求转发记录。
	 */
	private static final String ADTRAFFICHTTP_LOG_NAME = "adtraffichttp";

	/**
	 * 为了提醒异步日志性能，在记录业务事件日志时将直接采用Log4j的日志类org.apache.logging.log4j.Logger
	 */
	private final static org.apache.logging.log4j.Logger AdreqRecorder = LogManager.getLogger(ADREQUEST_LOG_NAME);
	private final static org.apache.logging.log4j.Logger AdeventRecorder = LogManager.getLogger(ADEVENT_LOG_NAME);
	private final static org.apache.logging.log4j.Logger AdbidreqRecorder = LogManager.getLogger(ADBIDREQUEST_LOG_NAME);
	private final static org.apache.logging.log4j.Logger AdTrafficHttpRecorder = LogManager.getLogger(ADTRAFFICHTTP_LOG_NAME);

	/**
	 * 拆分string.replaceAll(aa,bb);
	 */
	static final Pattern pattern = Pattern.compile("\\|");
	/**
	 * CR
	 */
	static final Pattern CR = Pattern.compile("\r");
	/**
	 * LF
	 */
	static final Pattern LF = Pattern.compile("\n");
	//
	static final String replacement = "%7c";
	//
	static final String space = " ";

	static {
		//设置log4j 采用全局异步日志处理方式
		System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
		//设置系统属性主机名用于日志文件名的命名
		System.setProperty("hostname", getHostName());
	}

	/**
	 * 获取hostname
	 * @return String
	 */
	public static String getHostName() {
        try {
            return IPUtils.getHostName().replaceAll("-","");
        } catch (Exception e) {
            throw new RuntimeException("fetch hostName error ",e);
        }
    }
	
	/* (non-Javadoc)
	 * @see cn.falconnect.adserver.adapter.IAdEventLogger#logAdserverEventLog(cn.falconnect.adserver.adapter.AdserverEventLog)
	 */
	@Override
	public void log(AdserverEventLog eventLog) {
		if(eventLog instanceof AdTrafficHttpLog){			
			logAdTrafficHttpLog((AdTrafficHttpLog) eventLog);
		}else if(eventLog instanceof AdActiveEventLog){
			logAdActiveEventLog((AdActiveEventLog) eventLog);
		}else if(eventLog instanceof AdTrackingEventLog){
			logAdTrackingEventLog((AdTrackingEventLog) eventLog);
		}else{
			// TODO 其他事件的日志
		}
	}
	
	/**
	 *  http请求转发记录。
	 * 
	 * 服务器
	 * 线程名 Thread.currentThread().getName()
	 * 请求时间 request.getRequstTime()
	 * 请求方式：post、get
	 * url request.getUrl()
	 * 协议 response.getProtocol()+response.getMajor()+response.getMinor()
	 * 返回状态 response.getStatusCode()
	 * 返回字节数 response.getLength()
	 * 响应时间 time
	 * 事件类型 :101 补量渠道  ,102 sts->gdt广告请求。TODO 未实现
	 * 扩展字段。
	 * @param eventLog
	 */
	private void logAdTrafficHttpLog(AdTrafficHttpLog eventLog) {
		Object[] fields = new Object[]{
				eventLog.getServerId(),
				eventLog.getRequstThreadName(),
				eventLog.getRequstTime(),
				eventLog.getHttpMethod(),
				eventLog.getUrl(),
				eventLog.getProtocol()+eventLog.getMajor()+eventLog.getMinor(),
				eventLog.getStatusCode(),
				eventLog.getLength(),
				eventLog.getTime(),
				//eventLog.getEventType(),
				eventLog.getExt()
				};
		AdTrafficHttpRecorder.info(new AdEventMessage(eventLog.getRequstTime(), fields));
	}

	/**
	 * 激活回调 logger记入。
	 * @param event
	 */
	private void logAdActiveEventLog(AdActiveEventLog event) {
		Object[] fields = new Object[]{
				event.getServerId(), 					// 1	server_id	服务器编号	每台服务器配置的唯一串号
				event.getEventType(),	            	// 2	event_type	行为类型	2 - 展示成功	3 - 点击跳转目标页面
				event.getGuid(),                    		// 3	guid	一个用户访问某个广告及后续行为的事务id
				event.getExceptionType(),           		// 4	exception_type	消息状态类型	0 - 正常
				event.getRequestIp(),               		// 5	request_ip	广告请求时的IP地址
				event.getAdspaceId(),               		// 6	adspace_id	广告位ID
				event.getAdFormat(),                		// 7	ad_format	广告类型	1 - 横幅 2 - 插屏 3 - 开屏 4 - 视频 5 - 原生
				event.getCreativeWidth(),           		// 8	creative_width	广告物料宽度
				event.getCreativeHeight(),          		// 9	creative_height	广告物料高度
				escapeSeparator(escapeLineBreak(event.getUa())),    	    // 10	ua	浏览器的user agent值
				event.getIp(),                      		// 11	ip	设备的IP地址	客户端ip
				event.getMuniqueType(),             		// 12	munique_type	跟踪使用的唯一串号类型	唯一串号依序作为后续消息跟踪的依据：
				event.getMuniqueId(),               		// 13	munique_id	跟踪使用的唯一串号	Muniquetype对应的ID，便于报告计算UV
				event.getMobOps(),                  		// 14	mob_ops	设备使用的运营商，MCC+MNC	0 - 未知
				escapeSeparator(event.getBrand()),       // 15	brand	设备制造/品牌
				escapeSeparator(event.getModel()),  		// 16	model	设备型号
				escapeSeparator(event.getOs()),          // 17	os	设备操作系统	操作系统
				event.getConnType(),                		// 18	conn_type	设备联网类型	网络环境
				event.getDeviceType(),              		// 19	device_type	设备类型	0 - 未知
				event.getScreenWidth(),             		// 20	screen_width	设备屏幕分辨率宽度，单位为像素
				event.getScreenHeight(),            		// 21	screen_height	设备屏幕分辨率高度，单位为像素
				event.getLatitude(),                		// 22	latitude	纬度
				event.getLongitude(),               		// 23	longitude	经度
				event.getCountryId(),               		// 24	country_id	国家ID
				event.getStateId(),                 		// 25	state_id	省份ID
				event.getCityId(),                  		// 26	city_id	城市ID
				event.getAreaId(),                  		// 27	area_id	地区ID	华东/华北/华南等。
				escapeSeparator(event.getBrowser()),     // 28	browser	浏览器	IE / Firefox / Chrome / Opera / Safari
				event.getCampaignId(),              		// 29	campaign_id	订单ID	server需要从基础表获取
				event.getStrategyId(),              		// 30	strategy_id	策略ID	server需要从基础表获取
				event.getCreativeId(),              		// 31	creative_id	创意ID	server需要从基础表获取
				event.getTemplateId(),              		// 32	template_id	创意模版ID	server需要从基础表获取
				event.getMaterialId(),              		// 33	material_id	素材ID
				event.getIncome(),                  		// 34	income	收入	当前行为产生的收入：收入 X 10000
				event.getPayment(),                  		// 35	payment	支出	当前行为产生的成本支出：支出 X 10000
				escapeSeparator(event.getImei()),			//36	imei	string	imei,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(event.getMac()),				//37	mac	string	mac去冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(event.getMac1()),			//38	mac1	string	mac保留冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(event.getIdfa()),			//39	idfa	string	idfa,md5加密	os=ios 时，idfa/udid 至少填写一项                                                 
				escapeSeparator(event.getAaid()),			//40	aaid	string	Android Advertising,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项          
				escapeSeparator(event.getAnid()),			//41	android_id	string	androidid,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(event.getUdid()),			//42	udid	string	iOS UDID,md5加密	os=ios 时，idfa/udid 至少填写一项                                             
				escapeSeparator(event.getDuid()),			//43	duid	string	Windows Phone 用户终端的 DUID,md5加密	os=windows phone 时，duid 必填                            
				escapeSeparator(event.getImeisha1()),		//44	imeisha1	String	imei的sha1值	　                                                                     
				escapeSeparator(event.getDpidsha1()),		//45	dpidsha1	String	androidid或idfa的sha1值	　                                                         
				escapeSeparator(event.getMacsha1()),			//46	macsha1	String	mac地址的sha1值	　                                                                         
				escapeSeparator(event.getImeimd5()),			//47	imeimd5	String	imei的md5值	　                                                                         
				escapeSeparator(event.getDpidmd5()),			//48	dpidmd5	String	androidid或idfa的md5值	　                                                                 
				escapeSeparator(event.getMacmd5()),			//49	macmd5	String	mac地址的md5值	　                                                                         
				escapeSeparator(event.getOpenUdid()),		//50	open_udid	String	ios的udid	　                                                                     
				escapeSeparator(event.getCustomId()),		//51	custom_id	String	自定义唯一串号：customizeId	上面没有对应的时候，来标注设备的唯一串号，扩展字段                                     
				event.getAdxType(),							//52	adx_type	int	adx的类型	参照枚举Exchange 1:falcon 2:adView  
				event.getChannel_id(),//渠道id
				event.getBchid(),//补量渠道标识
				event.getAvid(), //Avid dsp广告主标识
				event.getExceptionMsg()//异常信息
		};   
		AdeventRecorder.info(new AdEventMessage(event.getRequestTimestamp(), fields));
	}

	/**
	 * 记录广告监测事件
	 * @param event
	 * @since 2.0 
	 */
	private void logAdTrackingEventLog(AdTrackingEventLog event){
		Object[] fields = new Object[]{
				event.getServerId(), 					// 1	server_id	服务器编号	每台服务器配置的唯一串号
				event.getEventType(),	            	// 2	event_type	行为类型	2 - 展示成功	3 - 点击跳转目标页面
				event.getGuid(),                    		// 3	guid	一个用户访问某个广告及后续行为的事务id
				event.getExceptionType(),           		// 4	exception_type	消息状态类型	0 - 正常
				event.getRequestIp(),               		// 5	request_ip	广告请求时的IP地址
				event.getAdspaceId(),               		// 6	adspace_id	广告位ID
				event.getAdFormat(),                		// 7	ad_format	广告类型	1 - 横幅 2 - 插屏 3 - 开屏 4 - 视频 5 - 原生
				event.getCreativeWidth(),           		// 8	creative_width	广告物料宽度
				event.getCreativeHeight(),          		// 9	creative_height	广告物料高度
				escapeSeparator(escapeLineBreak(event.getUa())),    	    // 10	ua	浏览器的user agent值
				event.getIp(),                      		// 11	ip	设备的IP地址	客户端ip
				event.getMuniqueType(),             		// 12	munique_type	跟踪使用的唯一串号类型	唯一串号依序作为后续消息跟踪的依据：
				event.getMuniqueId(),               		// 13	munique_id	跟踪使用的唯一串号	Muniquetype对应的ID，便于报告计算UV
				event.getMobOps(),                  		// 14	mob_ops	设备使用的运营商，MCC+MNC	0 - 未知
				escapeSeparator(event.getBrand()),       // 15	brand	设备制造/品牌
				escapeSeparator(event.getModel()),  		// 16	model	设备型号
				escapeSeparator(event.getOs()),          // 17	os	设备操作系统	操作系统
				event.getConnType(),                		// 18	conn_type	设备联网类型	网络环境
				event.getDeviceType(),              		// 19	device_type	设备类型	0 - 未知
				event.getScreenWidth(),             		// 20	screen_width	设备屏幕分辨率宽度，单位为像素
				event.getScreenHeight(),            		// 21	screen_height	设备屏幕分辨率高度，单位为像素
				event.getLatitude(),                		// 22	latitude	纬度
				event.getLongitude(),               		// 23	longitude	经度
				event.getCountryId(),               		// 24	country_id	国家ID
				event.getStateId(),                 		// 25	state_id	省份ID
				event.getCityId(),                  		// 26	city_id	城市ID
				event.getAreaId(),                  		// 27	area_id	地区ID	华东/华北/华南等。
				escapeSeparator(event.getBrowser()),     // 28	browser	浏览器	IE / Firefox / Chrome / Opera / Safari
				event.getCampaignId(),              		// 29	campaign_id	订单ID	server需要从基础表获取
				event.getStrategyId(),              		// 30	strategy_id	策略ID	server需要从基础表获取
				event.getCreativeId(),              		// 31	creative_id	创意ID	server需要从基础表获取
				event.getTemplateId(),              		// 32	template_id	创意模版ID	server需要从基础表获取
				event.getMaterialId(),              		// 33	material_id	素材ID
				event.getIncome(),                  		// 34	income	收入	当前行为产生的收入：收入 X 10000
				event.getPayment(),                  		// 35	payment	支出	当前行为产生的成本支出：支出 X 10000
				escapeSeparator(event.getImei()),			//36	imei	string	imei,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(event.getMac()),				//37	mac	string	mac去冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(event.getMac1()),			//38	mac1	string	mac保留冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(event.getIdfa()),			//39	idfa	string	idfa,md5加密	os=ios 时，idfa/udid 至少填写一项                                                 
				escapeSeparator(event.getAaid()),			//40	aaid	string	Android Advertising,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项          
				escapeSeparator(event.getAnid()),			//41	android_id	string	androidid,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(event.getUdid()),			//42	udid	string	iOS UDID,md5加密	os=ios 时，idfa/udid 至少填写一项                                             
				escapeSeparator(event.getDuid()),			//43	duid	string	Windows Phone 用户终端的 DUID,md5加密	os=windows phone 时，duid 必填                            
				escapeSeparator(event.getImeisha1()),		//44	imeisha1	String	imei的sha1值	　                                                                     
				escapeSeparator(event.getDpidsha1()),		//45	dpidsha1	String	androidid或idfa的sha1值	　                                                         
				escapeSeparator(event.getMacsha1()),			//46	macsha1	String	mac地址的sha1值	　                                                                         
				escapeSeparator(event.getImeimd5()),			//47	imeimd5	String	imei的md5值	　                                                                         
				escapeSeparator(event.getDpidmd5()),			//48	dpidmd5	String	androidid或idfa的md5值	　                                                                 
				escapeSeparator(event.getMacmd5()),			//49	macmd5	String	mac地址的md5值	　                                                                         
				escapeSeparator(event.getOpenUdid()),		//50	open_udid	String	ios的udid	　                                                                     
				escapeSeparator(event.getCustomId()),		//51	custom_id	String	自定义唯一串号：customizeId	上面没有对应的时候，来标注设备的唯一串号，扩展字段                                     
				event.getAdxType(),							//52	adx_type	int	adx的类型	参照枚举Exchange 1:falcon 2:adView  
				event.getChannel_id(),
				event.getBchid(),//补量渠道标识 空占位
				"", //Avid dsp广告主标识 空占位
				event.getExceptionMsg()//异常信息
		};   
		AdeventRecorder.info(new AdEventMessage(event.getRequestTimestamp(), fields));
	}




	/*
	 * (non-Javadoc)
	 * @see cn.falconnect.adserver.adapter.IAdServerLogger#logAdRequest(cn.falconnect.adserver.context.AdContext)
	 */
	@Override
	public void logAdRequest(AdContext data) {
		Object[] fileds = new Object[]{
				data.getServerId(),						//服务器编号	每台服务器配置的唯一串号
				data.getVersion(),	    				//广告请求版本	广告请求接口协议版本
				data.getRequestIp(),    				//广告请求的ip	s2s，对方的server ip
				data.getAdSpaceId(),    				//广告位ID	创建于广告平台，媒体获取，通过此id可关联广告位，媒体，尺寸等等等等。
				data.getMediaCategory(),				//媒体类型	广告平台媒体分类（体育，财经，医疗）
				data.getAdFormat(),						//广告类型	"1：横幅 2：插屏 3：开屏 4：视频 5：原生"
				data.getAdSpaceWidth(),     			//广告位的宽度，单位为像素	请求当前的广告位尺寸-宽
				data.getAdSpaceHeight(),    			//广告位的高度，单位为像素	请求当前的广告位尺寸-高
				data.getAdSpaceRatio(),     			//广告位的尺寸比例	广告位宽度：广告位高度
				data.getMinDuration(),      			//视频广告支持的最短播放时长，单位为秒
				data.getMaxDuration(), 	    			//视频广告支持的最长播放时长，单位为秒
				escapeSeparator(escapeLineBreak(data.getUa())),			//浏览器的user agent值
				data.getIp(),							//设备的IP地址	客户端ip
				data.getImei(),							//imei md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项
				data.getMac(),							//mac	mac去冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项
				data.getMac1(),							//mac1	mac保留冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项
				data.getIdfa(),							//idfa	idfa,md5加密	os=ios 时，idfa/udid 至少填写一项
				data.getAaid(),							//aaid	Android Advertising,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项
				escapeSeparator(data.getAndroidId()),	//android_id	androidid,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项
				data.getUdid(),							//udid	iOS UDID,md5加密	os=ios 时，idfa/udid 至少填写一项
				escapeSeparator(data.getDuid()),		//duid	Windows Phone 用户终端的 DUID,md5加密	os=windows phone 时，duid 必填
				escapeSeparator(data.getVisitorId()),	//vistior_id	cookie的vid
				data.getMuniqueType(),					//munique_type	跟踪使用的唯一串号类型	"唯一串号依序作为后续消息跟踪的依据： 1 - mac 2 - mac1 3 - imei 4 - idfa 5 - duid 6 - androidid 7 - udid 8 - aaid 9 - cookie"
				escapeSeparator(data.getMuniqueId()),	//munique_id	跟踪使用的唯一串号	Muniquetype对应的ID，便于报告计算UV
				data.getMob_ops(),						//mob_ops	设备使用的运营商，MCC+MNC	"0：未知 1：中国移动 2：中国联通 3：中国电信"
				escapeSeparator(data.getBrand()),		//brand	设备制造/品牌
				escapeSeparator(data.getModel()),		//model	设备型号
				data.getOs(),							//os	设备操作系统	"操作系统 0：未知 1：android 2：ios 3：windows"
				escapeSeparator(data.getOsVersion()),	//os_version	设备操作系统版本号
				data.getConnType(),						//conn_type	设备联网类型	"网络环境 0：未知 1：wifi 2：2G 3：3G 4：4G"
				data.getDeviceType(),					//device_type	设备类型	"0 - 未知 1 - iPhone 2 - Android手机 3 - iPad 4 - Windows Phone 5 - Android平板 6 - 智能TV"
				data.getScreenWidth(),					//screen_width	设备屏幕分辨率宽度，单位为像素
				data.getScreenHeight(),					//screen_height	设备屏幕分辨率高度，单位为像素
				data.getScreenOritent(),				//screen_oritent 设备屏幕方向	"横竖屏。建议填写，可以帮助获取最优尺寸创意。 0：未知 1：竖屏 2：横屏"
				data.getLatitude(),						//latitude	纬度
				data.getLongitude(),					//longitude	经度
				data.getCountryId(),					//country_id	国家ID
				data.getStateId(),						//state_id	省份ID
				data.getCityId(),						//city_id	城市ID
				data.getAreaId(),						//area_id	地区ID	华东/华北/华南等。
				escapeSeparator(data.getBrowser()),		//browser	浏览器	IE / Firefox / Chrome / Opera / Safari
				data.getCampaignId(),					//campaign_id	订单ID
				data.getStrategyId(),					//strategy_id	策略ID
				data.getCreativeId(),					//creative_id	创意ID
				data.getTemplateId(),					//template_id	创意模版ID
				data.getMaterialId(),					//material_id	素材ID
				data.getFlag(),							//flag	请求状态	"0 - 正常 1 - 请求无广告位ID 2 - 请求无任何唯一设备ID"
				data.getGuid(),							//guid	一个用户访问某个广告及后续行为的事务id	用户，策略/创意，时间；可以用于广告后续行动的跟踪分析及作弊的分析等
				data.getForwardType(),					//转发类型 0：未转发 1：转发成功 2：转发失败
				data.getImeiori(),						//原始imei，建议和imei一起传给server端
				data.getMacori(),						//原始mac，建议和mac一起传给server端
				data.getIdfaori(),						//原始idfa，建议和idfa一起传给server端
				data.getAnidori(),						//原始androidid，建议和anid一起传给server端
				data.getReferer()						//先前的网页地址
		};
		AdreqRecorder.info(new AdEventMessage(data.getRequestTimestamp(), fileds));
	}

	/**
	 * 行为类型，展示.logger 记入。
	 * @param data
	 */
	public void logAdImpression(ClickPresentation data) {
		logAdClick(data);
	}

	/* (non-Javadoc)
	 * @see cn.falconnect.adserver.adapter.IAdServerLogger#logAdClick(cn.falconnect.adserver.port.presentation.ClickPresentation)
	 */
	@Override
	public void logAdClick(ClickPresentation data) {
		Object[] fields = new Object[]{
				data.getServerId(), 					// 1	server_id	服务器编号	每台服务器配置的唯一串号
				data.getEventType(),	            	// 2	event_type	行为类型	2 - 展示成功	3 - 点击跳转目标页面
				data.getGuid(),                    		// 3	guid	一个用户访问某个广告及后续行为的事务id
				data.getExceptionType(),           		// 4	exception_type	消息状态类型	0 - 正常
				data.getRequestIp(),               		// 5	request_ip	广告请求时的IP地址
				data.getAdspaceId(),               		// 6	adspace_id	广告位ID
				data.getAdFormat(),                		// 7	ad_format	广告类型	1 - 横幅 2 - 插屏 3 - 开屏 4 - 视频 5 - 原生
				data.getCreativeWidth(),           		// 8	creative_width	广告物料宽度
				data.getCreativeHeight(),          		// 9	creative_height	广告物料高度
				escapeSeparator(escapeLineBreak(data.getUa())),    	    // 10	ua	浏览器的user agent值
				data.getIp(),                      		// 11	ip	设备的IP地址	客户端ip
				data.getMuniqueType(),             		// 12	munique_type	跟踪使用的唯一串号类型	唯一串号依序作为后续消息跟踪的依据：
				data.getMuniqueId(),               		// 13	munique_id	跟踪使用的唯一串号	Muniquetype对应的ID，便于报告计算UV
				data.getMobOps(),                  		// 14	mob_ops	设备使用的运营商，MCC+MNC	0 - 未知
				escapeSeparator(data.getBrand()),       // 15	brand	设备制造/品牌
				escapeSeparator(data.getModel()),  		// 16	model	设备型号
				escapeSeparator(data.getOs()),          // 17	os	设备操作系统	操作系统
				data.getConnType(),                		// 18	conn_type	设备联网类型	网络环境
				data.getDeviceType(),              		// 19	device_type	设备类型	0 - 未知
				data.getScreenWidth(),             		// 20	screen_width	设备屏幕分辨率宽度，单位为像素
				data.getScreenHeight(),            		// 21	screen_height	设备屏幕分辨率高度，单位为像素
				data.getLatitude(),                		// 22	latitude	纬度
				data.getLongitude(),               		// 23	longitude	经度
				data.getCountryId(),               		// 24	country_id	国家ID
				data.getStateId(),                 		// 25	state_id	省份ID
				data.getCityId(),                  		// 26	city_id	城市ID
				data.getAreaId(),                  		// 27	area_id	地区ID	华东/华北/华南等。
				escapeSeparator(data.getBrowser()),     // 28	browser	浏览器	IE / Firefox / Chrome / Opera / Safari
				data.getCampaignId(),              		// 29	campaign_id	订单ID	server需要从基础表获取
				data.getStrategyId(),              		// 30	strategy_id	策略ID	server需要从基础表获取
				data.getCreativeId(),              		// 31	creative_id	创意ID	server需要从基础表获取
				data.getTemplateId(),              		// 32	template_id	创意模版ID	server需要从基础表获取
				data.getMaterialId(),              		// 33	material_id	素材ID
				data.getIncome(),                  		// 34	income	收入	当前行为产生的收入：收入 X 10000
				data.getPayment(),                  		// 35	payment	支出	当前行为产生的成本支出：支出 X 10000
				escapeSeparator(data.getImei()),			//36	imei	string	imei,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(data.getMac()),				//37	mac	string	mac去冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                          
				escapeSeparator(data.getMac1()),			//38	mac1	string	mac保留冒号、大写,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(data.getIdfa()),			//39	idfa	string	idfa,md5加密	os=ios 时，idfa/udid 至少填写一项                                                 
				escapeSeparator(data.getAaid()),			//40	aaid	string	Android Advertising,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项          
				escapeSeparator(data.getAnid()),			//41	android_id	string	androidid,md5加密	os=android 时，mac/mac1/imei/androidid/aaid 至少填写一项                  
				escapeSeparator(data.getUdid()),			//42	udid	string	iOS UDID,md5加密	os=ios 时，idfa/udid 至少填写一项                                             
				escapeSeparator(data.getDuid()),			//43	duid	string	Windows Phone 用户终端的 DUID,md5加密	os=windows phone 时，duid 必填                            
				escapeSeparator(data.getImeisha1()),		//44	imeisha1	String	imei的sha1值	　                                                                     
				escapeSeparator(data.getDpidsha1()),		//45	dpidsha1	String	androidid或idfa的sha1值	　                                                         
				escapeSeparator(data.getMacsha1()),			//46	macsha1	String	mac地址的sha1值	　                                                                         
				escapeSeparator(data.getImeimd5()),			//47	imeimd5	String	imei的md5值	　                                                                         
				escapeSeparator(data.getDpidmd5()),			//48	dpidmd5	String	androidid或idfa的md5值	　                                                                 
				escapeSeparator(data.getMacmd5()),			//49	macmd5	String	mac地址的md5值	　                                                                         
				escapeSeparator(data.getOpenUdid()),		//50	open_udid	String	ios的udid	　                                                                     
				escapeSeparator(data.getCustomId()),		//51	custom_id	String	自定义唯一串号：customizeId	上面没有对应的时候，来标注设备的唯一串号，扩展字段                                     
				data.getAdxType(),							//52	adx_type	int	adx的类型	参照枚举Exchange 1:falcon 2:adView                                                
				data.getChannel(),
				"",//补量渠道标识 空占位
				"", //Avid dsp广告主标识 空占位
				""//异常信息
		};   
		AdeventRecorder.info(new AdEventMessage(data.getRequestTimestamp(), fields));
	}

	public void logAdBidRequest(BidContext data) {
		Object[] fields = new Object[]{                 //1		request_timestamp	String	请求时间	请求时间戳，
				data.getServerId(),				        //2		server_id	int	服务器编号	每台服务器配置的唯一串号                                                    
				data.getAdxType(),                      //3		adx_type	int	adx的类型	参照枚举Exchange 1:falcon 2:adView	后续可以添加	　	　                   
				data.getBidId(),                        //4		bid_id	String	每次竞价请求的bidid	请求唯一串号                                                  
				data.getBidVersion(),                   //5		bid_version	String	请求的版本号	根据每家adx请求中要求的版本号记录                                          
				data.getFeeType(),                      //6		fee_type	String	计费方式	cpc,cpm多个用逗号隔开                                              
				data.getBidFloor(),                     //7		bid_floor	double	最低竞标价格	底价，数值为cpc，cpm价格,单位 RMB	　	　	　                           
				data.getPriceUnit(),                    //8		price_unit	String	价格单位	USD，RMB 默认是RMB	　	　	　                                   
				data.getTransactionType(),              //9		transaction_type	int	竞价类型		　	　                                               
				escapeSeparator(data.getAppId()),           //10	app_id	String	appId	adx的app唯一标识	便于后面查找问题	否	　                                   
				escapeSeparator(data.getAppName()),         //11	app_name	String	app名称	　	　	　	　                                               
				data.getAppType(),                      	//12	app_type[1]	String	app类型	需要做映射，多个id之间用逗号隔开	　	是	　                               
				escapeSeparator(data.getAppDomain()),       //13	app_domain	String	app域名	　	　	　	　                                               
				escapeSeparator(data.getAppVersion()),		//14	app_version	String	App版本	　	　	　	　                                               
				escapeSeparator(data.getAppBundle()),       //15	app_bundle	String	BundleID或者包名                                                        
				escapeSeparator(data.getAppStoreUrl()),     //16	app_store_url	String	市场下载地址	安卓或者ios应用商店的下载地址	　	　	　                                    
				data.getAppKeywords(),                  //17	app_keywords	String	关键字	多个关键字之间用逗号隔开	　	　	　                                    
				data.getAppIsPay(),                     //18	app_is_pay	int	是否为付费App                                                                     
				data.getAdFormat(),                     //19	ad_format	int	广告类型	1:横幅                                                                      
				data.getIncludeAdvertiser(),	        //20	include_advertiser	String	广告主缩略名称数组，只接受这些广告主	                                        
				data.getAdxTagId(),				        //21	adx_tag_id	String	广告位置标识	当原生时候的需要根据这个字段 去找到对应的原生模板	　	　	　                       
				data.getExcludeIndustryCategory(),      //22	exclude_industry_category	String	拒绝接受的行业广告类型	多个用逗号隔开	　	　	　                       
				data.getExcludeAdvertiserDomain(),      //23	exclude_advertiser_domain	String	拒绝接受的广告主名单，采用域名标示广告主	多个用逗号隔开	　	　	　           
				data.getAdspaceWidth(),			        //24	adspace_width	String	广告位的宽度，单位为像素	　	　	　	　                                   
				data.getAdspaceHeight(),		        //25	adspace_height	String	广告位的高度，单位为像素	　	　	　	　                                   
				data.getScreenPosition(),		        //26	screen_position	String	广告在屏幕上的位置	　	　	　	　                                       
				data.getExcludeCreativeType(),	        //27	exclude_creative_type	String	拒绝的广告创意属性	多个用逗号隔开	　	　	　                           
				data.getIncludeMimes(),			        //28	include_mimes	String	广告物料形式支持，已支持部分不列入。	　	　	　	　                               
				data.getAdxSpaceId(),			        //29	adx_adspace_id	String	adx分配广告位的唯一标识	现在应该是没有的	　	　	　                           
				data.getAdspaceSize(),			        //30	adspace_size	String	广告位的尺寸比例　	　                                                   
				data.getMinDuration(),			        //31	min_duration	int	视频广告支持的最短播放时长，单位为秒	　	　	　	　                                   
				data.getMaxDuration(),			        //32	max_duration	int	视频广告支持的最长播放时长，单位为秒	　	　	　	　                                   
				data.getDnt(),					        //33	dnt	int	是否不允许广告追踪                                                                       
				escapeSeparator(escapeLineBreak(data.getUa())),					        //34	ua	String	浏览器的user agent值	　	　	　	　                                               
				data.getIp(),					        //35	ip	String	设备的IP地址	　	　	　	　                                                       
				data.getImei(),					        //36	imei	String	设备的imei号	　	　	　	　                                               
				data.getMac(),					        //37	mac	String	终端的mac地址（去掉冒号分隔符）	　	　	　	　                                           
				data.getMac1(),					        //38	mac1	String	终端的mac地址（保留冒号分隔符）	　	　	　	　                                       
				data.getIdfa(),					        //39	idfa	String	ios的idfa	　	　	　	　                                               
				data.getAaid(),					        //40	aaid	String	android advertising id	　                                               
				data.getAnid(),					        //41	anid	String	android id	　	　	　	　                                               
				escapeSeparator(data.getUdid()),					        //42	udid	String	ios udid	　	　	　	　                                               
				escapeSeparator(data.getDuid()),					        //43	duid	String 	windows phone 的duid	　	　	　	　                                       
				escapeSeparator(data.getImeisha1()),	 			        //44	imeisha1	String	imei的sha1值	　	　	　	　                                           
				escapeSeparator(data.getDpidsha1()),				        //45	dpidsha1	String	androidid或idfa的sha1值	　	　	　	　                               
				escapeSeparator(data.getMacsha1()),				        //46	macsha1	String	mac地址的sha1值	　	　	　	　                                               
				escapeSeparator(data.getImeimd5()),				        //47	imeimd5	String	imei的md5值	　	　	　	　                                               
				escapeSeparator(data.getDpidmd5()),				        //48	dpidmd5	String	androidid或idfa的md5值	　	　	　	　                                       
				escapeSeparator(data.getMacmd5()),				        //49	macmd5	String	mac地址的md5值	　	                                                        
				escapeSeparator(data.getOpenUdid()),				        //50	open_udid	String	ios的udid	　	　	　	　                                           
				escapeSeparator(data.getCustomId()),				        //51	custom_id	String	自定义唯一串号：customizeId	上面没有对应的时候，来标注设备的唯一串号，扩展字段	　	　	　           
				escapeSeparator(data.getVisitorId()),			        //52	vistior_id	String	cookie的vid	　	　	　	　                                           
				data.getMuniqueType(),			        //53	munique_type	String	跟踪使用的唯一串号类型	　	　	　	　
				escapeSeparator(data.getMuniqueId()),			        //54	munique_id	String	跟踪使用的唯一串号	　	　	　	　                                           
				data.getMobOps(),				        //55	mob_ops	int	设备使用的运营商，MCC+MNC	0 - 未知	　	　	　                                       
				escapeSeparator(data.getBrand()),				        //56	brand	String	设备制造/品牌	　	　	　	　                                                   
				escapeSeparator(data.getModal()),				        //57	model	String	设备型号	　	　	　	　                                                   
				data.getOs(),					        //58	os	int	设备操作系统	操作系统                                                                    
				data.getOsVersion(),			        //59	os_version	String	设备操作系统版本号	　	　	　	　                                           
				data.getJsEnable(),				        //60	js_enable	int	是否支持Javascript脚本                                                        
				data.getConnType(),				        //61	conn_type	int	设备联网类型	　	　	　	　                                                   
				data.getDeviceType(),			        //62	device_type	int	设备类型	　	　	　	　                                                   
				data.getScreenDensity(),		        //63	screen_density	float	设备屏幕像素密度	　	　	　	　                                       
				data.getScreenWidth(),			        //64	screen_width	int	设备屏幕分辨率宽度，单位为像素	　	　	　	　                                       
				data.getScreenHeight(),			        //65	screen_height	int	设备屏幕分辨率高度，单位为像素	　	　	　	　                                       
				data.getScreenOritent(),		        //66	screen_oritent	int	设备屏幕方向	　	　	　	　                                               
				data.getLatitude(),				        //67	latitude	float	纬度	　	　	　	　                                                   
				data.getLongitude(),			        //68	longitude	float	经度	　	　	　	　                                                   
				data.getCountryId(),			        //69	country_id	int	国家ID	　	　	　	　                                                   
				data.getStateId(),				        //70	state_id	int	省份ID                                                                    
				data.getCityId(),				        //71	city_id	int	城市ID	　	　	　	　                                                       
				data.getDistrictId(),			        //72	district_id	int	地区ID	　	　	　	　                                                   
				data.getBrowser(),				        //73	browser	String	浏览器	　	　	　	　                                                       
				escapeSeparator(data.getTopRefUrl()),			        //74	top_ref_url	String	前一页面URL	　	　	　	　                                               
				escapeSeparator(data.getRefUrl()),				        //75	ref_url	String	当前页面的URL	　	　	　	　                                               
				data.getUserId(),				        //76	userid	String	用户在媒体的唯一标识	　	　	　	　                                               
				data.getGender(),				        //77	gender	int	0:未知 1:男 2:女	　	　	　	　                                               
				data.getAgeLow(),				        //78	age_low	int	最小年龄	　	　	　	　                                                       
				data.getAgeHigh(),				        //79	age_high	int	最大年龄	　	　	　	                                                    
				data.getInteresting(),			        //80	interesting	String	用户兴趣或倾向，以逗号分隔                                                       
				data.getLanguage(),				        //81	language	String	语言环境	　	　	　	　                                               
				data.getImpId(),				        //82	imp_id	String	imp唯一标识，由媒体生成	adx在impression中会带过来	　	　	　                           
				data.getCampaignId(),			        //83	campaign_id	int	订单ID	　	　	　	　                                                   
				data.getStrategyId(),			        //84	strategy_id	int	策略ID	　	　	　	　                                                   
				data.getCreativeId(),			        //85	creative_id	int	创意ID	　	　	　	　                                                   
				data.getTemplateId(),			        //86	template_id	int	创意模版ID	　	　	　	　                                                   
				data.getMaterialId(),			        //87	material_id	int	物料ID	　	　	　	　                                                   
				data.getBidPrice(),				        //88	bid_price	double	实际出价	　	　	　	　                                               
				data.getBidPriceType(),			        //89	bid_price_type	String	出价类型	cpc,cpm	　	　	　                                       
				data.getStrategies(),			        //90	strategies	String	出价策略集合	使用逗号隔开	　	　	　                                           
				data.getFlag(),					        //91	flag	　	请求状态	0 - 正常 1 - 异常（无返回广告）
				data.getGuid(),							//92    每次印象的唯一id
				data.getCreativeSpec(),					//93    创意规格。
				data.getChannel(),						//94    接入渠道标识
				data.getAudienceId(),					//95 dmp人群包id
				data.getAdxCreativeSpecsStr()			//96  广点通的规格(全部)
		}; 
		AdbidreqRecorder.info(new AdEventMessage(data.getRequestTimestamp(), fields));
	}
	
	/**
	 * 分隔符号 | 转义
	 * @param str
	 * @return
	 */
	private String escapeSeparator(String str){
		if(str == null){
			return null;
		}
		return  pattern.matcher(str).replaceAll(replacement);
	}
	
	/**
	 * LF和CR 转义
	 * @param str
	 * @return
	 */
	private String escapeLineBreak(String str){
		if(str == null){
			return null;
		}
		String _str = CR.matcher(str).replaceAll(space);
		return  LF.matcher(_str).replaceAll(space);
	}

	public void logWinNotice(WinNoticePresentation data) {
		logAdClick(data);
	}
}   